package io.gitee.zhangbinhub.admin.controller.openinner

import io.gitee.zhangbinhub.acp.boot.exceptions.WebException
import io.gitee.zhangbinhub.acp.boot.log.LogAdapter
import io.gitee.zhangbinhub.admin.common.api.CommonPath
import io.gitee.zhangbinhub.admin.common.api.WorkFlowApi
import io.gitee.zhangbinhub.admin.common.base.BaseController
import io.gitee.zhangbinhub.admin.common.vo.InfoVo
import io.gitee.zhangbinhub.admin.resource.server.po.ProcessHandlingPo
import io.gitee.zhangbinhub.admin.resource.server.po.ProcessStartPo
import io.gitee.zhangbinhub.admin.resource.server.po.ProcessTerminationPo
import io.gitee.zhangbinhub.admin.resource.server.vo.ProcessInstanceVo
import io.gitee.zhangbinhub.admin.resource.server.vo.ProcessTaskVo
import io.gitee.zhangbinhub.admin.workflow.service.WorkFlowService
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*

@Validated
@RestController
@RequestMapping(CommonPath.openInnerBasePath)
@Tag(name = "工作流引擎（内部开放接口）")
class OpenInnerWorkFlowController @Autowired
constructor(
    private val logAdapter: LogAdapter,
    private val workFlowService: WorkFlowService
) : BaseController() {
    @Operation(summary = "获取流程任务信息", description = "获取指定流程任务")
    @GetMapping(value = [WorkFlowApi.task + "/{taskId}"], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun queryTaskInfo(
        @Parameter(description = "流程任务ID", required = true)
        @PathVariable(name = "taskId") taskId: Long
    ): ResponseEntity<ProcessTaskVo> = ResponseEntity.ok(workFlowService.findTaskByIdOpen(taskId))

    @Operation(summary = "启动流程", description = "启动指定的流程，并关联唯一业务主键")
    @PutMapping(value = [WorkFlowApi.start], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun start(@RequestBody @Validated processStartPo: ProcessStartPo): ResponseEntity<InfoVo> =
        ResponseEntity.ok(InfoVo(message = workFlowService.startFlow(processStartPo).id.toString()))

    @Operation(summary = "启动流程", description = "启动指定的流程，并关联唯一业务主键")
    @PutMapping(value = [WorkFlowApi.start + "/{userId}"], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun startByUser(
        @PathVariable(name = "userId") userId: String,
        @RequestBody @Validated processStartPo: ProcessStartPo
    ): ResponseEntity<InfoVo> =
        ResponseEntity.ok(InfoVo(message = workFlowService.startFlow(processStartPo, userId).id.toString()))

    @Operation(summary = "流程处理", description = "可选通过或不通过")
    @PostMapping(value = [WorkFlowApi.process + "/{userId}"], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun processByUser(
        @PathVariable(name = "userId") userId: String,
        @RequestBody @Validated processHandlingPo: ProcessHandlingPo
    ): ResponseEntity<InfoVo> = workFlowService.skip(processHandlingPo, userId).let {
        ResponseEntity.ok(InfoVo(message = "流程处理完成"))
    }

    @Operation(summary = "查询待办任务")
    @GetMapping(
        value = [WorkFlowApi.pending + "/{processInstanceId}/{userId}"],
        produces = [MediaType.APPLICATION_JSON_VALUE]
    )
    @Throws(WebException::class)
    fun pendingByUser(
        @PathVariable(name = "processInstanceId") processInstanceId: Long,
        @PathVariable(name = "userId") userId: String
    ): ResponseEntity<List<ProcessTaskVo>> = ResponseEntity.ok(workFlowService.findTaskList(processInstanceId, userId))

    @Operation(summary = "流程强制结束")
    @DeleteMapping(value = [WorkFlowApi.termination], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun termination(@RequestBody @Validated processTerminationPo: ProcessTerminationPo): ResponseEntity<InfoVo> =
        workFlowService.findProcessInstance(processTerminationPo.processInstanceId!!).let { instance ->
            if (instance.finished) {
                logAdapter.warn("流程已结束，无法再次终止该流程！")
            }
            workFlowService.terminationFlow(processTerminationPo).let {
                ResponseEntity.ok(InfoVo(message = "强制结束流程实例成功"))
            }
        }

    @Operation(summary = "获取流程实例", description = "获取指定流程实例")
    @GetMapping(
        value = [WorkFlowApi.instance + "/{processInstanceId}"],
        produces = [MediaType.APPLICATION_JSON_VALUE]
    )
    @Throws(WebException::class)
    fun queryInstance(
        @Parameter(description = "流程实例id", required = true)
        @PathVariable(name = "processInstanceId")
        processInstanceId: Long
    ): ResponseEntity<ProcessInstanceVo> = ResponseEntity.ok(workFlowService.findProcessInstance(processInstanceId))
}
